﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SCMS.CoreBusinessLogic.ExpenseClaim;
using SCMS.CoreBusinessLogic.OrderRequest;
using SCMS.CoreBusinessLogic.TenderAnalysis;
using SCMS.UI.Models;
using SCMS.CoreBusinessLogic.Web;
using SCMS.Model;
using SCMS.CoreBusinessLogic.ActionFilters;
using SCMS.UI.GeneralHelper;
using System.Text;
using SCMS.CoreBusinessLogic.Security;
using SCMS.CoreBusinessLogic.NotificationsManager;
using SCMS.Resource;

namespace SCMS.UI.Controllers
{
    [MyException]
    //[SessionExpireFilter]
    public class ExpenseClaimController : PortalBaseController
    {
        private IExpenseClaimService ECService;
        private IOrderRequest oRService;
        private ITAnalysisService tAervice;
        private INotificationService notificationService;

        public ExpenseClaimController(IPermissionService permissionService, IExpenseClaimService ECService, IOrderRequest oRService, ITAnalysisService tAervice,
            INotificationService notificationService, IUserContext uc):base (uc, permissionService)
        {
            this.ECService = ECService;
            this.oRService = oRService;
            this.tAervice = tAervice;
            this.notificationService = notificationService;
        }
        //
        // GET: /ExpenseClaim/

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult LoadExpenseClaim()
        {
            ExpenseClaim model = new ExpenseClaim();
            model.EntityExpseRqst = new Model.ExpenseRequest();
            model.Currencies = new SelectList(oRService.GetCurrencies(countryProg.Id), "Id", "ShortName");
            model.EntityExpseRqst.ClaimBy = currentStaff.Id;
            model.Staffs = new SelectList(tAervice.GetStaffs(countryProg.Id), "StaffID", "StaffName");
            model.EntityExpseRqst.RefNumber = string.Format("--{0}--", Resources.Global_String_NewECF);
            model.EntityExpseRqst.RequestDate = DateTime.Today;
            return View(model);
        }

        public ActionResult EditECF(Guid id)
        {
            ExpenseRequest ecf = ECService.GetExpenseClaimById(id);
            ExpenseClaim model = new ExpenseClaim
            {
                EntityExpseRqst = ecf,
                Currencies = new SelectList(oRService.GetCurrencies(countryProg.Id), "Id", "ShortName"),
                Staffs = new SelectList(tAervice.GetStaffs(countryProg.Id), "StaffID", "StaffName")
            };
            return View("LoadExpenseClaim", model);
        }

        public ActionResult DeleteECF(Guid id)
        {
            ECService.DeleteECF(id);
            return ViewExpsClaims();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SaveEClaim(Models.ExpenseClaim entity)
        {
            entity.EntityExpseRqst.CountryProgrammeId = countryProg.Id;
            entity.EntityExpseRqst.PreparedBy = currentStaff.Id;
            entity.EntityExpseRqst.IsReviewed = false;
            entity.EntityExpseRqst.IsAuthorized = false;
            entity.EntityExpseRqst.PreparedOn = DateTime.Now;
            ECService.SaveECF(entity.EntityExpseRqst);

            return LoadExpenseClaimItems(entity.EntityExpseRqst.Id);
        }

        private ActionResult LoadExpenseClaimItems(Guid ecfId, List<BudgetCheckResult> bcrList = null)
        {
            ExpenseRequest ecf = ECService.GetExpenseClaimById(ecfId);
            List<ExpenseItem> ecfItems = ECService.GetExpenseItems(ecfId);
            Models.ExpenseClaim model = new ExpenseClaim { EntityExpseRqst = ecf, EcfItems = new List<ExpenseClaimItem>(), BudgetCheckResults = bcrList };
            foreach (ExpenseItem ecfItem in ecfItems)
            {
                model.EcfItems.Add(new ExpenseClaimItem { EntityExpseItem = ecfItem });
            }

            ViewBag.CurrencyId = ecf.ExpenseCurrencyId;
            ViewBag.ExpsCID = ecf.Id;
            return View("LoadExpenseClaimItems", model);
        }

        public ActionResult LoadExpseItem(Guid ecfId, Guid currId)
        {
            List<ProjectDonor> pdList = oRService.GetProjectNos(countryProg.Id);
            List<BudgetLineView> blList = pdList.Count > 0 ? oRService.GetProjectBugdetLines(pdList[0].Id) : null;
            if (blList == null) blList = new List<BudgetLineView>();
            ExpenseClaimItem model = new ExpenseClaimItem()
            {
                EntityExpseItem = new ExpenseItem(),
                ProjectNos = new SelectList(pdList, "Id", "ProjectNumber"),
                BudgetLines = new SelectList(blList, "Id", "Description")
            };
            ViewBag.Action = Resources.Global_String_Save;
            ViewBag.CurrencyId = currId;
            ViewBag.ExpsCID = ecfId;
            return View("LoadExpseItem", model);
        }

        public ActionResult EditItem(Guid id)
        {
            ExpenseItem ecfItem = ECService.GetExpenseItemById(id);
            List<ProjectDonor> pdList = oRService.GetProjectNos(countryProg.Id);
            List<BudgetLineView> blList = pdList.Count > 0 ? oRService.GetProjectBugdetLines((Guid)ecfItem.ProjectBudget.BudgetCategory.ProjectDonorId) : null;
            if (blList == null) blList = new List<BudgetLineView>();
            ExpenseClaimItem model = new ExpenseClaimItem()
            {
                EntityExpseItem = ecfItem,
                ProjectDonorId = (Guid)ecfItem.ProjectBudget.BudgetCategory.ProjectDonorId,
                ProjectNos = new SelectList(pdList, "Id", "ProjectNumber"),
                BudgetLines = new SelectList(blList, "Id", "Description")
            };
            model.Amount = Math.Round(model.Amount, 2);
            ViewBag.Action = Resources.Global_String_Save;
            ViewBag.CurrencyId = ecfItem.ExpenseRequest.ExpenseCurrencyId;
            ViewBag.ExpsCID = ecfItem.ExpenseId;
            return View("LoadExpseItem", model);
        }

        public ActionResult RemoveItem(Guid id)
        {
            ExpenseItem ecfItem = ECService.GetExpenseItemById(id);
            Guid ecfId = ecfItem.ExpenseId;
            ECService.DeleteECFItem(id);
            return LoadExpenseClaimItems(ecfId);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SaveExpseItem(Guid id, ExpenseClaimItem entity)
        {
            entity.EntityExpseItem.ExpenseId = id;
            if (ECService.SaveExpenseClaimItem(entity.EntityExpseItem))
            {
                ViewBag.Response = 1;
                ViewBag.msg = Resources.ExpenseClaimController_String_ECFItemSaved;
            }
            else { ViewBag.Response = 0; ViewBag.msg = Resources.Global_String_AnErrorOccurred; }
            return LoadExpenseClaimItems(id);
        }

        public ActionResult GetBudgetLines(Guid id)
        {
            StringBuilder blineOption = new StringBuilder();
            blineOption.Append("<select class=\"dpl\" id=\"BudgetLineID\" name=\"EntityExpseItem.BudgetLineId\" onchange = \"javascript:checkBalance()\"><option value=\"\">" + Resources.Global_String_PleaseSelect + "</option>");
            List<Model.BudgetLineView> BLines = oRService.GetProjectBugdetLines(id);
            foreach (BudgetLineView item in BLines)
                blineOption.Append("<option value=\"" + item.Id + "\">" + item.Description + "</option>");
            blineOption.Append("</select>");
            blineOption.Append("<span class=\"field-validation-valid\" data-valmsg-for=\"EntityExpseItem.BudgetLineId\" data-valmsg-replace=\"true\"></span>");
            ViewBag.Html = blineOption.ToString();
            return View("HTMLResponse");
        }

        public ActionResult SubmitECF(Guid Id)
        {
            ExpenseRequest ecf = ECService.GetExpenseClaimById(Id);

            List<BudgetCheckResult> bcrList = ECService.RunFundsAvailableCheck(Id);
            if (bcrList.Count > 0)
                return LoadExpenseClaimItems(Id, bcrList: bcrList);//Render ECF with message saying funds not sufficient

            ecf.PreparedOn = DateTime.Now;
            ecf.IsAuthorized = false;
            ecf.IsRejected = false;
            ecf.IsSubmitted = true;
            ecf.RefNumber = ECService.GenerateUniquNumber(countryProg);
            ECService.SaveApprovedECF(ecf);
            notificationService.SendToAppropriateApprover(NotificationHelper.ecfCode, NotificationHelper.reviewCode, ecf.Id);
            return ViewExpsClaims();
        }

        public ActionResult ViewExpsClaims()
        {
            using (var db = new SCMSEntities())
            {
                List<Models.ViewExpsClaims> itemmodel = new List<ViewExpsClaims>();
                List<Model.ExpenseRequest> ExpsList = db.ExpenseRequests.Where(p => p.CountryProgrammeId == countryProg.Id).OrderByDescending(e => e.PreparedOn).ToList<ExpenseRequest>();
                foreach (ExpenseRequest item in ExpsList)
                {
                    var model = new ViewExpsClaims()
                    {
                        EntityExpseRqst = item,
                        ExpsItems = ECService.GetExpenseItems(item.Id),
                        PreparedBy = db.VStaffDetails.First(p => p.StaffID == item.PreparedBy),
                        ExpsCurrency = db.Currencies.First(p => p.Id == item.ExpenseCurrencyId),
                        Converted2Currency = db.Currencies.First(p => p.Id == item.CurrencyConvertedTo),
                        ClaimBy = db.VStaffDetails.First(p => p.StaffID == item.ClaimBy),
                        ApprovedBy = db.VStaffDetails.FirstOrDefault(p => p.StaffID == (item.ReviewedBy == null ? Guid.Empty : item.ReviewedBy)),
                        AuthorizedBy = db.VStaffDetails.FirstOrDefault(p => p.StaffID == (item.AuthorizedBy == null ? Guid.Empty : item.AuthorizedBy))
                    };
                    itemmodel.Add(model);
                }
                return View("ViewExpsClaims", itemmodel);
            }

        }

        public ActionResult ViewExpsClaimsDetails(Guid id, bool checkPost = false)
        {
            Models.ViewExpsClaims model = ExpsClaimExtension.PrepareECFModel(ECService, id);
            ViewBag.MBCurrency = mbCurrency.ShortName;
            //Manage approval link
            string actionType = null;
            if (model.EntityExpseRqst.IsReviewed && !model.EntityExpseRqst.IsAuthorized)
                actionType = NotificationHelper.authorizationCode;
            else if (model.EntityExpseRqst.IsSubmitted && !model.EntityExpseRqst.IsReviewed)
                actionType = NotificationHelper.reviewCode;
            model.CanEdit = (model.EntityExpseRqst.IsSubmitted != true && model.EntityExpseRqst.IsRejected != true && model.EntityExpseRqst.PreparedBy == currentStaff.Id) ||
                    (model.EntityExpseRqst.IsSubmitted && model.EntityExpseRqst.IsRejected && !model.EntityExpseRqst.IsReviewed && model.EntityExpseRqst.PreparedBy == currentStaff.Id);                
            if (actionType != null)
                model.CanApprove = notificationService.CanApprove(currentUser, NotificationHelper.ecfCode, actionType, model.EntityExpseRqst.Id);
            else
                model.CanApprove = false;

            //Manage Post Funds Button
            if (userContext.HasPermission(StandardPermissionProvider.ExpenseClaimPostFunds) && checkPost)
                foreach (var ecf in ECService.GetExpenseClaimsForPosting(countryProg.Id, currentUser))
                {
                    if (ecf.Id.Equals(model.EntityExpseRqst.Id))
                    {
                        model.CanPostFunds = true;
                        break;
                    }
                }

            return View("ViewExpsClaimsDetails", model);
        }
    }
}
